package org.huatek.anders.aspect;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.huatek.anders.annotation.RequestLog;
import org.huatek.anders.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

/**
 * @author anders
 */
@Slf4j
@Aspect
@Component
public class RequestLogAspect {


    @Pointcut("@annotation(org.huatek.anders.annotation.RequestLog)")
    public void logPointCut() {

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        RequestLog requestLog = method.getAnnotation(RequestLog.class);
        if (requestLog.isBefore()) {
            printRequestLog(point, signature, requestLog, 0);
        }
        //执行方法
        Object result = point.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;

        //保存日志
        if (requestLog.isAfter()) {
            printRequestLog(point, signature, requestLog, time);
        }

        return result;
    }

    private void printRequestLog(ProceedingJoinPoint joinPoint, MethodSignature signature, RequestLog requestLog, long time) {
        StringBuilder sb = new StringBuilder();

        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        String ipAddr="";
        sb.append(System.getProperty("line.separator"));
        sb.append("请求URL:").append(requestLog.value());
        sb.append(System.getProperty("line.separator"));
        //方法名
        sb.append("接口请求方法：").append(className).append(".").append(methodName).append("()");
        sb.append(System.getProperty("line.separator"));

        //请求的参数
        Object[] args = joinPoint.getArgs();
        log.info(Arrays.toString(args));
        ObjectMapper mapper = new ObjectMapper();
        try {
            /// Map<String, Object> argMap = new HashMap<>(16);
            for (Object arg : args) {
                if (arg instanceof HttpServletRequest) {
                    ipAddr = IpUtils.getIpAddr((HttpServletRequest) arg);
                    continue;
                }
///                if (arg instanceof ServiceImpl) {
//                com.baomidou.mybatisplus.service.impl.ServiceImpl
//                    continue;
//                }
                if (arg instanceof HttpServletResponse) {
                    continue;
                }
                sb.append("接口请求参数：");
                sb.append(System.getProperty("line.separator"));
                sb.append(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(arg));
                sb.append(System.getProperty("line.separator"));
                /// argMap.put(index + "",mapper.writeValueAsString(arg));
            }
            /// String argsStr = mapper.writeValueAsString(argMap);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        //设置IP地址
        sb.append("IP地址：");
        sb.append(System.getProperty("line.separator"));
        sb.append(ipAddr);
        sb.append(System.getProperty("line.separator"));
        //执行时长
        sb.append("执行时长：");
        sb.append(System.getProperty("line.separator"));
        sb.append(time);
        sb.append(System.getProperty("line.separator"));
        log.info(sb.toString());
    }
}
